mxlpy 0.20.0__py3-none-any.whl → 0.22.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mxlpy/__init__.py +5 -1
- mxlpy/carousel.py +166 -0
- mxlpy/compare.py +2 -6
- mxlpy/experimental/diff.py +1 -1
- mxlpy/fit.py +386 -44
- mxlpy/identify.py +20 -16
- mxlpy/integrators/int_scipy.py +3 -0
- mxlpy/label_map.py +5 -5
- mxlpy/linear_label_map.py +3 -1
- mxlpy/mc.py +24 -20
- mxlpy/mca.py +9 -7
- mxlpy/meta/__init__.py +5 -3
- mxlpy/meta/codegen_latex.py +44 -30
- mxlpy/meta/codegen_model.py +174 -0
- mxlpy/meta/{codegen_modebase.py → codegen_mxlpy.py} +35 -29
- mxlpy/meta/source_tools.py +408 -167
- mxlpy/meta/sympy_tools.py +117 -0
- mxlpy/model.py +528 -224
- mxlpy/parallel.py +7 -6
- mxlpy/report.py +153 -90
- mxlpy/sbml/_export.py +11 -8
- mxlpy/sbml/_import.py +7 -7
- mxlpy/scan.py +32 -20
- mxlpy/simulator.py +240 -59
- mxlpy/symbolic/symbolic_model.py +29 -17
- mxlpy/types.py +45 -20
- mxlpy/units.py +128 -0
- {mxlpy-0.20.0.dist-info → mxlpy-0.22.0.dist-info}/METADATA +3 -1
- mxlpy-0.22.0.dist-info/RECORD +58 -0
- mxlpy/meta/codegen_py.py +0 -115
- mxlpy-0.20.0.dist-info/RECORD +0 -55
- {mxlpy-0.20.0.dist-info → mxlpy-0.22.0.dist-info}/WHEEL +0 -0
- {mxlpy-0.20.0.dist-info → mxlpy-0.22.0.dist-info}/licenses/LICENSE +0 -0
mxlpy/__init__.py
CHANGED
@@ -52,6 +52,7 @@ from . import (
|
|
52
52
|
plot,
|
53
53
|
report,
|
54
54
|
sbml,
|
55
|
+
units,
|
55
56
|
)
|
56
57
|
from .integrators import DefaultIntegrator, Scipy
|
57
58
|
from .label_map import LabelMapper
|
@@ -61,7 +62,7 @@ from .model import Model
|
|
61
62
|
from .scan import steady_state, time_course, time_course_over_protocol
|
62
63
|
from .simulator import Simulator
|
63
64
|
from .symbolic import SymbolicModel, to_symbolic_model
|
64
|
-
from .types import Derived, IntegratorProtocol, unwrap
|
65
|
+
from .types import Derived, IntegratorProtocol, Parameter, Variable, unwrap
|
65
66
|
|
66
67
|
with contextlib.suppress(ImportError):
|
67
68
|
from .integrators import Assimulo
|
@@ -87,9 +88,11 @@ __all__ = [
|
|
87
88
|
"LabelMapper",
|
88
89
|
"LinearLabelMapper",
|
89
90
|
"Model",
|
91
|
+
"Parameter",
|
90
92
|
"Scipy",
|
91
93
|
"Simulator",
|
92
94
|
"SymbolicModel",
|
95
|
+
"Variable",
|
93
96
|
"cartesian_product",
|
94
97
|
"compare",
|
95
98
|
"distributions",
|
@@ -110,6 +113,7 @@ __all__ = [
|
|
110
113
|
"time_course",
|
111
114
|
"time_course_over_protocol",
|
112
115
|
"to_symbolic_model",
|
116
|
+
"units",
|
113
117
|
"unwrap",
|
114
118
|
]
|
115
119
|
|
mxlpy/carousel.py
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
"""Reaction carousel."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import itertools as it
|
6
|
+
from copy import deepcopy
|
7
|
+
from dataclasses import dataclass, field
|
8
|
+
from functools import partial
|
9
|
+
from typing import TYPE_CHECKING
|
10
|
+
|
11
|
+
import pandas as pd
|
12
|
+
|
13
|
+
from mxlpy import parallel, scan
|
14
|
+
|
15
|
+
__all__ = ["Carousel", "CarouselSteadyState", "CarouselTimeCourse", "ReactionTemplate"]
|
16
|
+
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
from collections.abc import Iterable, Mapping
|
19
|
+
|
20
|
+
from mxlpy import Model
|
21
|
+
from mxlpy.types import Array, IntegratorType, RateFn
|
22
|
+
|
23
|
+
|
24
|
+
@dataclass
|
25
|
+
class ReactionTemplate:
|
26
|
+
"""Template for a reaction in a model."""
|
27
|
+
|
28
|
+
fn: RateFn
|
29
|
+
args: list[str]
|
30
|
+
additional_parameters: dict[str, float] = field(default_factory=dict)
|
31
|
+
|
32
|
+
|
33
|
+
@dataclass
|
34
|
+
class CarouselSteadyState:
|
35
|
+
"""Time course of a carousel simulation."""
|
36
|
+
|
37
|
+
carousel: list[Model]
|
38
|
+
results: list[scan.TimePoint]
|
39
|
+
|
40
|
+
def get_variables_by_model(self) -> pd.DataFrame:
|
41
|
+
"""Get the variables of the time course results, indexed by model."""
|
42
|
+
return pd.DataFrame({i: r.variables for i, r in enumerate(self.results)}).T
|
43
|
+
|
44
|
+
|
45
|
+
@dataclass
|
46
|
+
class CarouselTimeCourse:
|
47
|
+
"""Time course of a carousel simulation."""
|
48
|
+
|
49
|
+
carousel: list[Model]
|
50
|
+
results: list[scan.TimeCourse]
|
51
|
+
|
52
|
+
def get_variables_by_model(self) -> pd.DataFrame:
|
53
|
+
"""Get the variables of the time course results, indexed by model."""
|
54
|
+
return pd.concat({i: r.variables for i, r in enumerate(self.results)})
|
55
|
+
|
56
|
+
|
57
|
+
def _dict_product[T1, T2](d: Mapping[T1, Iterable[T2]]) -> Iterable[dict[T1, T2]]:
|
58
|
+
yield from (dict(zip(d.keys(), x, strict=True)) for x in it.product(*d.values()))
|
59
|
+
|
60
|
+
|
61
|
+
def _make_reaction_carousel(
|
62
|
+
model: Model, rxns: dict[str, list[ReactionTemplate]]
|
63
|
+
) -> Iterable[Model]:
|
64
|
+
for d in _dict_product(rxns):
|
65
|
+
new = deepcopy(model)
|
66
|
+
for rxn, template in d.items():
|
67
|
+
new.add_parameters(template.additional_parameters)
|
68
|
+
new.update_reaction(name=rxn, fn=template.fn, args=template.args)
|
69
|
+
yield new
|
70
|
+
|
71
|
+
|
72
|
+
class Carousel:
|
73
|
+
"""A carousel of models with different reaction templates."""
|
74
|
+
|
75
|
+
variants: list[Model]
|
76
|
+
|
77
|
+
def __init__(
|
78
|
+
self,
|
79
|
+
model: Model,
|
80
|
+
variants: dict[str, list[ReactionTemplate]],
|
81
|
+
) -> None:
|
82
|
+
"""Initialize the carousel with a model and reaction templates."""
|
83
|
+
self.variants = list(
|
84
|
+
_make_reaction_carousel(
|
85
|
+
model=model,
|
86
|
+
rxns=variants,
|
87
|
+
)
|
88
|
+
)
|
89
|
+
|
90
|
+
def time_course(
|
91
|
+
self,
|
92
|
+
time_points: Array,
|
93
|
+
*,
|
94
|
+
y0: dict[str, float] | None = None,
|
95
|
+
integrator: IntegratorType | None = None,
|
96
|
+
) -> CarouselTimeCourse:
|
97
|
+
"""Simulate the carousel of models over a time course."""
|
98
|
+
results = [
|
99
|
+
i[1]
|
100
|
+
for i in parallel.parallelise(
|
101
|
+
partial(
|
102
|
+
scan._time_course_worker, # noqa: SLF001
|
103
|
+
time_points=time_points,
|
104
|
+
integrator=integrator,
|
105
|
+
y0=y0,
|
106
|
+
),
|
107
|
+
list(enumerate(self.variants)),
|
108
|
+
)
|
109
|
+
]
|
110
|
+
|
111
|
+
return CarouselTimeCourse(
|
112
|
+
carousel=self.variants,
|
113
|
+
results=results,
|
114
|
+
)
|
115
|
+
|
116
|
+
def protocol_time_course(
|
117
|
+
self,
|
118
|
+
protocol: pd.DataFrame,
|
119
|
+
*,
|
120
|
+
y0: dict[str, float] | None = None,
|
121
|
+
integrator: IntegratorType | None = None,
|
122
|
+
) -> CarouselTimeCourse:
|
123
|
+
"""Simulate the carousel of models over a protocol time course."""
|
124
|
+
results = [
|
125
|
+
i[1]
|
126
|
+
for i in parallel.parallelise(
|
127
|
+
partial(
|
128
|
+
scan._protocol_worker, # noqa: SLF001
|
129
|
+
protocol=protocol,
|
130
|
+
integrator=integrator,
|
131
|
+
y0=y0,
|
132
|
+
),
|
133
|
+
list(enumerate(self.variants)),
|
134
|
+
)
|
135
|
+
]
|
136
|
+
|
137
|
+
return CarouselTimeCourse(
|
138
|
+
carousel=self.variants,
|
139
|
+
results=results,
|
140
|
+
)
|
141
|
+
|
142
|
+
def steady_state(
|
143
|
+
self,
|
144
|
+
*,
|
145
|
+
y0: dict[str, float] | None = None,
|
146
|
+
integrator: IntegratorType | None = None,
|
147
|
+
rel_norm: bool = False,
|
148
|
+
) -> CarouselSteadyState:
|
149
|
+
"""Simulate the carousel of models over a time course."""
|
150
|
+
results = [
|
151
|
+
i[1]
|
152
|
+
for i in parallel.parallelise(
|
153
|
+
partial(
|
154
|
+
scan._steady_state_worker, # noqa: SLF001
|
155
|
+
integrator=integrator,
|
156
|
+
rel_norm=rel_norm,
|
157
|
+
y0=y0,
|
158
|
+
),
|
159
|
+
list(enumerate(self.variants)),
|
160
|
+
)
|
161
|
+
]
|
162
|
+
|
163
|
+
return CarouselSteadyState(
|
164
|
+
carousel=self.variants,
|
165
|
+
results=results,
|
166
|
+
)
|
mxlpy/compare.py
CHANGED
@@ -230,11 +230,7 @@ def protocol_time_courses(
|
|
230
230
|
) -> ProtocolComparison:
|
231
231
|
"""Compare the time courses of two models."""
|
232
232
|
return ProtocolComparison(
|
233
|
-
res1=unwrap(
|
234
|
-
|
235
|
-
),
|
236
|
-
res2=unwrap(
|
237
|
-
Simulator(m2).simulate_over_protocol(protocol=protocol).get_result()
|
238
|
-
),
|
233
|
+
res1=unwrap(Simulator(m1).simulate_protocol(protocol=protocol).get_result()),
|
234
|
+
res2=unwrap(Simulator(m2).simulate_protocol(protocol=protocol).get_result()),
|
239
235
|
protocol=protocol,
|
240
236
|
)
|
mxlpy/experimental/diff.py
CHANGED
@@ -187,7 +187,7 @@ def model_diff(m1: Model, m2: Model) -> ModelDiff:
|
|
187
187
|
if (v2 := m2._parameters.get(k)) is None: # noqa: SLF001
|
188
188
|
diff.missing_parameters.add(k)
|
189
189
|
elif v1 != v2:
|
190
|
-
diff.different_parameters[k] = (v1, v2)
|
190
|
+
diff.different_parameters[k] = (v1, v2) # type: ignore
|
191
191
|
|
192
192
|
for k, v1 in m1._variables.items(): # noqa: SLF001
|
193
193
|
if (v2 := m2._variables.get(k)) is None: # noqa: SLF001
|